package tencentcloud

import (
	"context"
	"encoding/base64"
	"fmt"
	"github.com/spf13/viper"
	"github.com/tencentyun/cos-go-sdk-v5"
	"go.uber.org/zap"
	"golang-sgg-daijia/pkg/log"
	"io"
	"net/http"
	"net/url"
	"strings"
	"time"
)

type CosClient interface {
	Put(ctx context.Context, path string, r io.Reader, uopt *cos.ObjectPutOptions) error
	GetImageUrl(ctx context.Context, path string) (string, error)
	TextAudit(ctx context.Context, content string) (int, string, error)
	ImageAudit(ctx context.Context, path string) (bool, error)
}

type cosClient struct {
	cosCli *cos.Client
	logger *log.Logger
	conf   *viper.Viper
}

func NewCosClient(
	cosCli *cos.Client,
	logger *log.Logger,
	conf *viper.Viper,
) CosClient {
	return &cosClient{
		cosCli: cosCli,
		logger: logger,
		conf:   conf,
	}
}

func NewCosCli(conf *viper.Viper) *cos.Client {
	// 1. 初始化小程序应用实例
	u, err := url.Parse(fmt.Sprintf("https://%s.cos.%s.myqcloud.com",
		conf.GetString("security.tencentclould.cos.bucket_private"),
		conf.GetString("security.tencentclould.region")))
	if err != nil {
		panic(err)
	}
	su, err := url.Parse(fmt.Sprintf("https://cos.%s.myqcloud.com", conf.GetString("security.tencentclould.region")))
	if err != nil {
		panic(err)
	}
	b := &cos.BaseURL{
		BucketURL:  u,
		ServiceURL: su,
	}
	client := cos.NewClient(b, &http.Client{
		Transport: &cos.AuthorizationTransport{
			SecretID:  conf.GetString("security.tencentclould.secret_Id"),
			SecretKey: conf.GetString("security.tencentclould.secret_key"),
		},
	})
	return client
}

func (cli *cosClient) Put(ctx context.Context, path string, r io.Reader, uopt *cos.ObjectPutOptions) error {
	_, err := cli.cosCli.Object.Put(ctx, path, r, uopt)
	if err != nil {
		cli.logger.WithContext(ctx).Error("cosClient|Put|Put", zap.Any("data", map[string]interface{}{
			"path": path,
		}), zap.Error(err))
		return err
	}
	return nil
}

// GetImageUrl 获取预前面url
func (cli *cosClient) GetImageUrl(ctx context.Context, path string) (string, error) {
	if path == "" {
		return "", nil
	}
	ak := cli.conf.GetString("security.cos.secret_Id")
	sk := cli.conf.GetString("security.cos.secret_key")
	presignedURL, err := cli.cosCli.Object.GetPresignedURL(ctx, http.MethodGet, path, ak, sk, time.Minute*15, nil)
	if err != nil {
		cli.logger.WithContext(ctx).Error("cosClient|GetImageUrl|GetPresignedURL", zap.Any("data", map[string]interface{}{
			"path": path,
		}), zap.Error(err))
		return "", err
	}
	return presignedURL.String(), nil
}

// TextAudit 文本审核
// 检测结果: 0（审核正常），1 （判定为违规敏感文件），2（疑似敏感，建议人工复核）。
func (cli *cosClient) TextAudit(ctx context.Context, content string) (int, string, error) {
	contentBase64 := base64.StdEncoding.EncodeToString([]byte(content))
	opt := &cos.PutTextAuditingJobOptions{
		InputContent: contentBase64,
		Conf: &cos.TextAuditingJobConf{
		},
	}
	res, _, err := cli.cosCli.CI.PutTextAuditingJob(ctx, opt)
	if err != nil {
		cli.logger.WithContext(ctx).Error("cosClient|TextAudit|PutTextAuditingJob", zap.Any("data", map[string]interface{}{
			"content": content,
		}), zap.Error(err))
		return 0, "", err
	}
	detail := res.JobsDetail
	var keywords []string
	for _, info := range detail.Section {
		if info.PornInfo != nil {
			keywords = append(keywords, info.PornInfo.Keywords)
		}
		if info.IllegalInfo != nil {
			keywords = append(keywords, info.IllegalInfo.Keywords)
		}
		if info.AbuseInfo != nil {
			keywords = append(keywords, info.AbuseInfo.Keywords)
		}
	}
	return detail.Result, strings.Join(keywords, ","), nil
}

// ImageAudit 图片审核
func (cli *cosClient) ImageAudit(ctx context.Context, path string) (bool, error) {
	res, _, err := cli.cosCli.CI.ImageAuditing(ctx, path, nil)
	if err != nil {
		cli.logger.WithContext(ctx).Error("cosClient|ImageAudit|ImageAuditing", zap.Any("data", map[string]interface{}{
			"path": path,
		}), zap.Error(err))
		return false, err
	}
	if !(res.PornInfo.HitFlag == 0) || !(res.AdsInfo == nil) ||
		!(res.TerrorismInfo.HitFlag == 0) || !(res.PoliticsInfo.HitFlag == 0) {
		return false, nil
	}
	return true, nil
}